using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Avalonia;
using Avalonia.Threading;
using JMCOM.Components.EpsonRobot.NodeFlow.Nodebehind;
using JMCOM.Components.EpsonRobot.NodeFlow.Syntax;

namespace JMCOM.Components.EpsonRobot.NodeFlow;

//节点根类
public class NodeViewModel : NodifyObservableObject
{
    public Guid Id { get; }
    public NodeViewModel(){

    }
    
    public NodeViewModel(Guid id)
        => Id = id;
    
    private string _title = string.Empty;
    public string Title
    {
        get => _title;
        set => SetProperty(ref _title, value);
    }
    
    private string? _name;
    public string? Name
    {
        get => _name;
        set => SetProperty(ref _name, value);
    }
    
    private Size _size;
    public Size Size
    {
        get => _size;
        set => SetProperty(ref _size, value);
    }

    private Point _location;
    public Point Location
    {
        get => _location;
        set
        {
            SetProperty(ref _location, value);
            // 同步更新X,Y属性，确保兼容性
            X = value.X;
            Y = value.Y;
        }
    }
    private Point _anchor;
    public Point Anchor
    {
        get => _anchor;
        set => SetProperty(ref _anchor, value);
    }
    private bool _isActive;
    public bool IsActive
    {
        get => _isActive;
        set => SetProperty(ref _isActive, value);
    }
    
    public bool IsEditable { get; set; } = true;

    // 保持X,Y属性用于Canvas绑定
    public double X { get; set; }
    public double Y { get; set; }
}

public class StateNodeViewModel : NodeViewModel
{
    
    private bool _isConnected;
    public bool IsConnected
    {
        get => _isConnected;
        set => SetProperty(ref _isConnected, value);
    }
    
     public Guid Id { get; }

        public StateNodeViewModel(Guid id)
            => Id = id;

        public StateNodeViewModel() : this(Guid.NewGuid()) { }

        // TODO: Can remove when auto layout is added
        private Point _location;
        public Point Location
        {
            get => _location;
            set => SetProperty(ref _location, value);
        }

        private Point _anchor;
        public Point Anchor
        {
            get => _anchor;
            set => SetProperty(ref _anchor, value);
        }

        private Size _size;
        public Size Size
        {
            get => _size;
            set => SetProperty(ref _size, value);
        }

        private string? _name;
        public string? Name
        {
            get => _name;
            set => SetProperty(ref _name, value);
        }

        private bool _isRenaming;
        public bool IsRenaming
        {
            get => _isRenaming;
            set => SetProperty(ref _isRenaming, value);
        }

        private bool _isActive;
        public bool IsActive
        {
            get => _isActive;
            set => SetProperty(ref _isActive, value);
        }

        private BlackboardItemReferenceViewModel? _actionReference;
        public BlackboardItemReferenceViewModel? ActionReference
        {
            get => _actionReference;
            set
            {
                if (SetProperty(ref _actionReference, value))
                {
                    SetAction(_actionReference);
                }
            }
        }

        public BlackboardItemViewModel? Action { get; private set; }

        public bool IsEditable { get; set; } = true;
        public StateMachineViewModel Graph { get; internal set; } = default!;
        public NodifyObservableCollection<StateNodeViewModel> Transitions { get; } = new NodifyObservableCollection<StateNodeViewModel>();

        private void SetAction(BlackboardItemReferenceViewModel? actionRef)
        {
            Action = BlackboardDescriptor.GetItem(actionRef);

            OnPropertyChanged(nameof(Action));
        }
        public virtual Action<Action> PropertyChangedDispatcher { get; set; } = Dispatcher.UIThread.Invoke;

        /// <summary>
        /// Occurs when a property value changes
        /// </summary>
        public event PropertyChangedEventHandler? PropertyChanged;

        /// <summary>
        /// Fires the PropertyChanged notification.
        /// </summary>
        /// <remarks>Specially named so that Fody.PropertyChanged calls it</remarks>
        /// <param name="propertyName">Name of the property to raise the notification for</param>
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChangedDispatcher(() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)));
        }
    
}

public class ConnectorViewModel : BindableBase
{
    private string _title = string.Empty;
    public string Title
    {
        get => _title;
        set => SetProperty(ref _title, value);
    }

    public NodeViewModel? Node { get; set; }
    
    private bool _isConnected;
    public bool IsConnected
    {
        get => _isConnected;
        set => SetProperty(ref _isConnected, value);
    }

    // 连接器类型 - 重要：用于区分输入输出
    public ConnectorType Type { get; set; } = ConnectorType.Input;

    private Point _anchor;
    public Point Anchor
    {
        get => _anchor;
        set => SetProperty(ref _anchor, value);
    }

    // 连接器的唯一标识
    public Guid Id { get; } = Guid.NewGuid();
}

public class ConnectionViewModel : BindableBase
{
    public ConnectionViewModel(NodeViewModel source, NodeViewModel target)
    {
        Source = source;
        Target = target; 
    }
    
    private NodeViewModel _source = default!;
    public NodeViewModel Source
    {
        get => _source;
        set => SetProperty(ref _source, value);
    }

    private NodeViewModel _target= default!;
    public NodeViewModel Target
    {
        get => _target;
        set => SetProperty(ref _target, value);
    }

    // 连接验证
    public bool CanConnect()
    {
        if (Source == null || Target == null)
            return false;

        // // 确保一个是输入，一个是输出
        // return Source.Type != Target.Type && 
        //        Source.Node != Target.Node; // 防止自连接
        return true;
    }
    
    private bool _isActive;
    public bool IsActive
    {
        get => _isActive;
        set => SetProperty(ref _isActive, value);
    }
}

// 连接器类型枚举
public enum ConnectorType
{
    Input,
    Output
}

//状态变换 转换
public class TransitionViewModel : NodifyObservableObject
{
    private StateNodeViewModel _source = default!;
    public StateNodeViewModel Source
    {
        get => _source;
        set => SetProperty(ref _source, value);
    }

    private StateNodeViewModel _target = default!;
    public StateNodeViewModel Target
    {
        get => _target;
        set => SetProperty(ref _target, value);
    }

    private BlackboardItemReferenceViewModel? _conditionReference;
    public BlackboardItemReferenceViewModel? ConditionReference
    {
        get => _conditionReference;
        set
        {
            if (SetProperty(ref _conditionReference, value))
            {
                SetCondition(_conditionReference);
            }
        }
    }

    public BlackboardItemViewModel? Condition { get; private set; }

    private bool _isActive;
    public bool IsActive
    {
        get => _isActive;
        set => SetProperty(ref _isActive, value);
    }

    private void SetCondition(BlackboardItemReferenceViewModel? conditionRef)
    {
        Condition = BlackboardDescriptor.GetItem(conditionRef);

        OnPropertyChanged(nameof(Condition));
    }
}